In [1]:
import numpy as np
import cv2
from matplotlib import pyplot as plt
%matplotlib inline

🐍Jupyter上でインライン表示するための関数を定義

  • 以降、こいつに画像データを渡せばインライン表示してくれる!
  • 読みやすくするためだけの関数
In [2]:
from IPython.display import display, Image

def display_cv_image(image, format='.png'):
    decoded_bytes = cv2.imencode(format, image)[1].tobytes()
    display(Image(data=decoded_bytes))

🐍まず原画像の確認

In [3]:
LoL = cv2.imread('resource/LumpofLeaves.png')
display_cv_image(LoL)

🐍もこもこした塊の部分を抽出したい

  • そのためまずはもこもこした塊の特徴をつかみたいので、適当にもこもこ部分を切り出してみる
  • ペイントで切り出しました
    • crop1 : 2000,2300を左上にして、600,350を切り取った
    • crop2 : 850, 1350を左上にして、300,200を切り取った
    • crop3 : 3250, 1600を左上にして、350,300を切り取った
In [4]:
crop1 = cv2.imread('resource/crop1.png')
display_cv_image(crop1)
In [5]:
crop2 = cv2.imread('resource/crop2.png')
display_cv_image(crop2)
In [6]:
crop3 = cv2.imread('resource/crop3.png')
display_cv_image(crop3)

🐍比較のため関係ないところも

In [7]:
crop4 = cv2.imread('resource/crop4.png')
display_cv_image(crop4)
In [8]:
crop5 = cv2.imread('resource/crop5.png')
display_cv_image(crop5)

🐍とりあえず切り取った画像をHSV色空間に変更してみる

  • こっちのほうがBGR形式よりも直感的にいじれる
  • HSV色空間についての解説はここ。むっちゃわかりやすい
  • もっとカラフルな画像でやってみたのも、hsv_example.htmlにある
  • むしろfor文の内包表記のほうが分かりづらいはず
In [9]:
imgs = [crop1, crop2, crop3, crop4, crop5]
hsv_imgs = [cv2.cvtColor(img, cv2.COLOR_BGR2HSV) for img in imgs]

🐍1つずつHSVのヒストグラムを表示してみる

In [10]:
for i, hsv_img in enumerate(hsv_imgs):

    h, s, v = hsv_img[:,:,0], hsv_img[:,:,1], hsv_img[:,:,2]

    hist_h, bins = np.histogram(h.ravel(),256,[0,256])
    hist_s, bins = np.histogram(s.ravel(),256,[0,256])
    hist_v, bins = np.histogram(v.ravel(),256,[0,256])

    plt.xlim(0, 255)
    plt.title('crop{}.png'.format(i+1))
    plt.plot(hist_h, "-h", label="Hue")
    plt.plot(hist_s, "-s", label="Saturation")
    plt.plot(hist_v, "-v", label="Value")
    plt.xlabel('Pixel Value', fontsize=20)
    plt.ylabel('Number of Pixels', fontsize=20)
    plt.legend()
    plt.grid()
    plt.show()

🎉ヒストグラムを見たところ…🎉

  • Hue(色相)の値が分類の手掛かりになると思っていたけど、灰色のコンクリート(crop5)も、crop1~4と同じような色相を表すってのが予想外だった。
  • Saturation(彩度)が小さければ小さいほど、色が薄くなるため、コンクリートはSaturationに閾値を設けると除外できそう
  • Value(明度)が小さいほど、黒っぽい色になる。今回の目当ての領域はたぶんあまり明度が小さくない領域であるため、Valueも利用できそう。
  • Hueの値を見る限り、たぶんHueは165~40あたりを狙えば取れそう…。
  • (参考)Hueの表↓
In [11]:
hue = cv2.imread('resource/Hue.png')
display_cv_image(hue)